﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Sim3D_practicum.Physics;

//254cm long x 127cm broad playing field
namespace Sim3D_practicum.Components
{
    class Pooltable : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Vector3 position;
        //private Cue _cue;
        private Hole[] holes = new Hole[6];
        private Border[] borders = new Border[6];
        private Ball[] balls = new Ball[2];
        private Lightbulb bulb;
        private Plain surface;
        private Ramp ramp;
        private Texture2D rect;
        private Rectangle artPositionScale;
        public SpriteBatch sprite;
        public static Vector3 GRAVITY = new Vector3( 0, -980, 0 );//mm/s²
        private const float width = 1270;
        private const float length = 2540;

        private Game _game;
        /// <summary>
        /// Pooltable. Doubles as the Game World.
        /// </summary>
        /// <param name="position"></param>
        /// <param name="game"></param>
        public Pooltable( Vector3 position, Game game )
            : base( game )
        {
            _game = game;

            this.position = position;
            surface = new Plain(new Vector3(width,0,0), new Vector3(0,0,length), new Vector3(250, 0, 250));
            holes[0] = new Hole( Vector3.Add( position, new Vector3( ) ), game );
            holes[1] = new Hole( Vector3.Add( position, new Vector3( width, 0, 0 ) ), game );
            holes[2] = new Hole( Vector3.Add( position, new Vector3( 0, 0, width ) ), game );
            holes[3] = new Hole( Vector3.Add( position, new Vector3( width, 0, width ) ), game );
            holes[4] = new Hole( Vector3.Add( position, new Vector3( 0, 0, length ) ), game );
            holes[5] = new Hole( Vector3.Add( position, new Vector3( width, 0, length ) ), game );
            //Top
            borders[0] = new Border( Vector3.Add( position, new Vector3( 57, 0, 0 ) ),
                new Vector3( 1, 0, 0 ), new Vector3( 0, 0, -1 ), game );
            //Upper Left
            borders[1] = new Border( Vector3.Add( position, new Vector3( 0, 0, 57 ) ),
                new Vector3( 0, 0, 1 ), new Vector3( -1, 0, 0 ), game );
            //Lower Left
            borders[2] = new Border( Vector3.Add( position, new Vector3( 0, 0, 57 * 3 + Border.length ) ),
                new Vector3( 0, 0, 1 ), new Vector3( -1, 0, 0 ), game );
            //Bottem
            borders[3] = new Border( Vector3.Add( position, new Vector3( 57, 0, length ) ),
                new Vector3( 1, 0, 0 ), new Vector3( 0, 0, 1 ), game );
            //Upper right
            borders[4] = new Border( Vector3.Add( position, new Vector3( width, 0, 57 ) ),
               new Vector3( 0, 0, 1 ), new Vector3( 1, 0, 0 ), game );
            //Lower right
            borders[5] = new Border( Vector3.Add( position, new Vector3( width, 0, 57 * 3 + Border.length ) ),
                new Vector3( 0, 0, 1 ), new Vector3( 1, 0, 0 ), game );

            SetUpBalls( );

            balls[1] = new Ball( Vector3.Add( position, new Vector3( 750, 150, 0 ) ), game );
            //balls[1].Velocity = new Vector3( -150, 0, -150 );

            balls[0] = new Ball( Vector3.Add( position, new Vector3( 750, 14.4f, 1250 ) ), game );
            balls[0].Velocity = new Vector3( 150, 0, -150 );
            bulb = new Lightbulb(Vector3.Add(position, new Vector3(width / 2, 1000, length / 2)), game);
            ramp = new Ramp(Vector3.Add(position, new Vector3(0, 0, 500)), 150f, new Vector3(0, 0, 500),game);
            //balls[1] = new Ball(Vector3.Add(position, new Vector3(100, 120, 300)), game);
            //_cue = new Cue( position, game );

            artPositionScale = new Rectangle(
                Calculator.mmToPixel( position.X ),
                Calculator.mmToPixel( position.Z ),
                Calculator.mmToPixel( 1270 ),
                Calculator.mmToPixel( 2540 ) );
        }

        private void SetUpBalls( )
        {
            balls[0] = new Ball( Vector3.Add( position, new Vector3( 750, 0, 750 ) ), _game );
            balls[0].Velocity = new Vector3( );

            //balls[1] = new Ball( Vector3.Add( position, new Vector3( 700, 0, 700 ) ), _game );
            //balls[1].Velocity = new Vector3( );

            //balls[2] = new Ball( Vector3.Add( position, new Vector3( 800, 0, 700 ) ), _game );
            //balls[2].Velocity = new Vector3( );

            //balls[3] = new Ball( Vector3.Add( position, new Vector3( 650, 0, 650 ) ), _game );
            //balls[3].Velocity = new Vector3( );

            //balls[4] = new Ball( Vector3.Add( position, new Vector3( 750, 0, 650 ) ), _game );
            //balls[4].Velocity = new Vector3( );

            //balls[5] = new Ball( Vector3.Add( position, new Vector3( 850, 0, 650 ) ), _game );
            //balls[5].Velocity = new Vector3( );

            //balls[6] = new Ball( Vector3.Add( position, new Vector3( 600, 0, 600 ) ), _game );
            //balls[6].Velocity = new Vector3( );

            //balls[7] = new Ball( Vector3.Add( position, new Vector3( 700, 0, 600 ) ), _game );
            //balls[7].Velocity = new Vector3( );

            //balls[8] = new Ball( Vector3.Add( position, new Vector3( 800, 0, 600 ) ), _game );
            //balls[8].Velocity = new Vector3( );

            //balls[9] = new Ball( Vector3.Add( position, new Vector3( 900, 0, 600 ) ), _game );
            //balls[9].Velocity = new Vector3( );

            //balls[10] = new Ball( Vector3.Add( position, new Vector3( 550, 0, 550 ) ), _game );
            //balls[10].Velocity = new Vector3( );

            //balls[11] = new Ball( Vector3.Add( position, new Vector3( 650, 0, 550 ) ), _game );
            //balls[11].Velocity = new Vector3( );

            //balls[12] = new Ball( Vector3.Add( position, new Vector3( 750, 0, 550 ) ), _game );
            //balls[12].Velocity = new Vector3( );

            //balls[13] = new Ball( Vector3.Add( position, new Vector3( 850, 0, 550 ) ), _game );
            //balls[13].Velocity = new Vector3( );

            //balls[14] = new Ball( Vector3.Add( position, new Vector3( 950, 0, 550 ) ), _game );
            //balls[14].Velocity = new Vector3( );
        }

        public override void Initialize( )
        {
            for ( int i = 0; i < holes.Length; i++ )
            {
                holes[i].Initialize( );
            }

            foreach ( Border b in borders )
            {
                if ( b != null )
                    b.Initialize( );
            }
            for ( int i = 0; i < balls.Length; i++ )
            {
                if ( balls[i] != null )
                    balls[i].Initialize( );
            }
            bulb.Initialize( );
            ramp.Initialize();
            base.Initialize( );
        }

        protected override void LoadContent( )
        {
            rect = Game.Content.Load<Texture2D>( "TableGreen" );
            base.LoadContent( );
        }

        override public void Draw( GameTime gameTime )
        {
            sprite.Begin( );
            sprite.Draw( rect, artPositionScale, Color.White );
            sprite.End();
            ramp.Draw(gameTime, sprite);
            for ( int i = 0; i < 6; i++ )
            {
                if ( borders[i] != null )
                    borders[i].Draw( gameTime, sprite );
                holes[i].Draw( gameTime, sprite );
            }
            for ( int i = 0; i < balls.Length; i++ )
            {
                balls[i].Draw( gameTime, sprite );
            }
            bulb.Draw(gameTime, sprite);
            base.Draw( gameTime );
        }

        public override void Update( GameTime gameTime )
        {
            bulb.Update(gameTime);
            foreach ( Border border in borders )
            {
                if ( border != null )
                    foreach ( Plain plain in border.box )
                    {
                        if ( plain != null )
                        {
                            foreach ( IBallCollision ball in balls )
                            {
                                if (ball != null)
                                {
                                    Vector3 v;
                                    if (plain.CheckForCollision(ball, gameTime, out v))
                                    {
                                        System.Diagnostics.Debug.WriteLine(ball.Velocity);
                                        System.Diagnostics.Debug.WriteLine(v);
                                    }
                                    plain.CheckForCollision(ball, gameTime);
                                }
                            }
                        }
                    }
            }           
            //check ball with borders
            for ( int i = 0; i < balls.Length; i++ )
            {
                Ball ball = balls[i];
                if ( ball != null )
                {
                    ramp.surface.CheckForCollision(ball, gameTime);
                    //check ball with other balls
                    //check ball with pooltable
                    collideTable( ball, gameTime );                   
                    for ( int j = i; j < balls.Length; j++ )
                    {
                        Ball otherBallz = balls[j];
                        if ( otherBallz != null && !otherBallz.Equals( ball ) )
                        {
                            ball.CheckForCollision( otherBallz );
                        }
                    }
                    ball.Update(gameTime);                    
                }
            }
            base.Update( gameTime );
        }
        public void collideTable( IBallCollision b, GameTime gt )
        {
            //if collide==true
            //thus: if on the table and not on the holes
            //b.Velocity *= 0.997f;
            bool hole = false;
            for ( int i = 0; i < 6; i++ )
            {
                hole |= holes[i].collide( b as Ball );
            }
            if ( !hole )
            {
                surface.CheckForCollision( b, gt );
            }
        }
    }
}